﻿using UnityEngine;

using Message;
using System.Collections.Generic;
using System.Timers;

/// <summary>
/// 玩家移动控制
/// </summary>
public class PlayerMoveControl : MonoBehaviour
{
    /// <summary>
    /// 摇杆
    /// </summary>
    public Joystick joystick;
    /// <summary>
    /// 旋转角度
    /// </summary>
    private float angle;
    /// <summary>
    /// 是否在玩家控制中
    /// </summary>
    private bool isCtrl = true;

    Vector3 vecMove;
    /// <summary>
    /// 位置
    /// </summary>
    Vector3 pos;
    /// <summary>
    /// 旋转
    /// </summary>
    Quaternion qu;

    /// <summary>
    /// 移动速度
    /// </summary>
    public float moveSpeed = 50;

    /// <summary>
    /// 位置同步200毫秒一次
    /// </summary>
    public static float posRate = 200;
    /// <summary>
    /// 定时器
    /// </summary>
    Timer timer = new Timer(posRate);

    /// <summary>
    /// 周围的玩家
    /// </summary>
    public Dictionary<int, GameObject> otherPlayer = new Dictionary<int, GameObject>();
    /// <summary>
    /// 当前的位置信息
    /// </summary>
    public Dictionary<int, Trans> oldTrans = new Dictionary<int, Trans>();
    /// <summary>
    /// 新的位置信息
    /// </summary>
    public Dictionary<int, Trans> newTrans = new Dictionary<int, Trans>();

    public List<int> otherPlayerUids = new List<int>();

    void Start()
    {
        //注册周围玩家的位置信息
        MsgMgr.Instance.AddListener(typeof(SToCMoves).ToString(), OnOtherMoves);
        timer.Elapsed += new ElapsedEventHandler(HandleMainTimer);
        timer.AutoReset = false;
        timer.Enabled = true;
    }

    // Update is called once per frame
    void Update()
    {
        if (joystick != null && isCtrl)
        {
            vecMove = new Vector3(joystick.Direction.x, 0, joystick.Direction.y) * Time.deltaTime * moveSpeed / 10;
            transform.localPosition += vecMove;
            angle = Mathf.Atan2(joystick.Direction.x, joystick.Direction.y) * Mathf.Rad2Deg - 10;
            transform.localRotation = Quaternion.Euler(Vector3.up * angle);
            pos = transform.position;
            qu = transform.rotation;
        }
    }

    bool isLerping = false;
    float lerpTimeLength = 0.3f;
    float timeStartedLerping;
    void FixedUpdate()
    {
        if (isLerping)
        {
            float timeSinceStarted = Time.time - timeStartedLerping;
            float percentageComplete = timeSinceStarted / lerpTimeLength; 
            foreach (int uid in newTrans.Keys)
            {
                otherPlayer[uid].transform.position = Vector3.Lerp(new Vector3(oldTrans[uid].x, oldTrans[uid].y, oldTrans[uid].z),
                  new Vector3(newTrans[uid].x, newTrans[uid].y, newTrans[uid].z), percentageComplete);
                Quaternion q1 = new Quaternion();
                q1.eulerAngles = new Vector3(0, oldTrans[uid].angle, 0);
                Quaternion q2 = new Quaternion();
                q2.eulerAngles = new Vector3(0, newTrans[uid].angle, 0);

                otherPlayer[uid].transform.rotation = Quaternion.Lerp(q1, q2, percentageComplete);
            }
            if (percentageComplete >= 1.0f)
            {
                isLerping = false;
            }
        }
    }

    private void HandleMainTimer(object sender, ElapsedEventArgs e)
    {
        SendMove();
        timer.Start();
    }

    /// <summary>
    /// 向服务器发送位置旋转信息
    /// </summary>
    void SendMove()
    {
        CToSMove ctsm = new CToSMove();
        ctsm.uid = GlobeData.uid;
        ctsm.x = pos.x;
        ctsm.y = pos.y;
        ctsm.z = pos.z;
        ctsm.angle = qu.eulerAngles.y;
        NetMgr.Instance.Send(ctsm);
    }

    void OnOtherMoves(object[] args)
    {
        Loom.QueueOnMainThread(() =>
        { 
            //更新位置信息 
            SToCMoves stcm = args[0] as SToCMoves;
            otherPlayerUids.Clear();
            oldTrans.Clear();
            newTrans.Clear();
            //Debug.Log(stcm.moves.Count);  
            for (int i = 0; i < stcm.moves.Count; i++)
            {
                CToSMove ctsm = stcm.moves[i];
                if (ctsm.uid != GlobeData.uid)
                {
                    //Debug.Log("Uid:" + ctsm.uid);
                    if (!otherPlayerUids.Contains(ctsm.uid))
                    {
                        otherPlayerUids.Add(ctsm.uid);
                    }
                    if (otherPlayer.ContainsKey(ctsm.uid))
                    {
                        Trans t1 = new Trans();
                        t1.x = otherPlayer[ctsm.uid].transform.position.x;
                        t1.y = otherPlayer[ctsm.uid].transform.position.y;
                        t1.z = otherPlayer[ctsm.uid].transform.position.z;
                        t1.angle = otherPlayer[ctsm.uid].transform.rotation.eulerAngles.y;
                        oldTrans.Add(ctsm.uid, t1);
                        Trans t2 = new Trans();
                        t2.x = ctsm.x;
                        t2.y = ctsm.y;
                        t2.z = ctsm.z;
                        t2.angle = ctsm.angle;
                        newTrans.Add(ctsm.uid, t2);
                    }
                    else
                    {
                        Debug.Log("here");
                        GameObject obj = ResMgr.Instance.Load("player");
                        ResMgr.Instance.Unload("player", false);
                        //添加其他玩家模型
                        GameObject otherPlayerObj = Instantiate(obj);
                        otherPlayerObj.name = ctsm.uid.ToString();
                        otherPlayerObj.transform.Find("Text").GetComponent<TextMesh>().text = ctsm.uname;
                        //设置位置信息
                        otherPlayerObj.transform.position = new Vector3(ctsm.x, ctsm.y, ctsm.z);
                        Quaternion q = new Quaternion();
                        q.eulerAngles = new Vector3(0, ctsm.angle, 0);
                        otherPlayerObj.transform.rotation = q;
                        otherPlayer.Add(ctsm.uid, otherPlayerObj);
                    }
                }
            }

            foreach (int uid in otherPlayer.Keys)
            {
                if (!otherPlayerUids.Contains(uid))
                {
                    //删除丢失的玩家 
                    Destroy(otherPlayer[uid]);
                    otherPlayer.Remove(uid);
                }
            }

            isLerping = true;
            timeStartedLerping = Time.time;

        });
    }

    private void OnApplicationQuit()
    {
        timer.Stop();
    }

    public struct Trans
    {
        public float x;
        public float y;
        public float z;
        public float angle;
    }
}